home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / tipx / xfer / tiprz.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-11  |  38.8 KB  |  1,731 lines

  1. char *numeric_revision = "tiprz 1.00";
  2. /*+-------------------------------------------------------------------------
  3.     tiprz.c - X/Y/ZMODEM receive program
  4.   Derived from public domain source by Chuck Forsberg, Omen Technologies
  5.   wht%n4hgf@emory.mathcs.emory.edu
  6.  
  7.   Defined functions:
  8.     SIGALRM_handler()
  9.     arg_token(parsestr,termchars)
  10.     bye_bye(sig)
  11.     cancel_transaction(sig)
  12.     close_and_report()
  13.     flushline()
  14.     fname_split(cmd,arg,arg_max_quan,narg_rtn)
  15.     fname_too_long(fname)
  16.     fname_truncated()
  17.     getfree()
  18.     isanylc(str)
  19.     main(argc,argv,envp)
  20.     make_dirs(pathname)
  21.     mkdir(dpath,dmode)
  22.     procheader(name)
  23.     purgeline()
  24.     readline(timeout)
  25.     rzfile()
  26.     rzfiles()
  27.     send_ZFIN_and_exit()
  28.     send_cancel()
  29.     sendline(c)
  30.     substr(str,token)
  31.     sys2(shellcmd)
  32.     tryz()
  33.     uncaps(str)
  34.     usage(fail_reason)
  35.     wcgetsec(rxbuf,maxtime)
  36.     wcreceive(argc,argp)
  37.     wcrx()
  38.     wcrxpn(rpn)
  39.     write_sec_to_disk(buf,n)
  40.     xsendline(c)
  41.  
  42.       Usage:    tiprz -Z [-abeuy]    (ZMODEM)
  43.                 tiprz -Y [-abuy]     (YMODEM)
  44.                 tiprz -X [-abc] file (XMODEM or XMODEM-1k)
  45.  
  46.           -a ASCII transfer (strip CR)
  47.           -b Binary transfer for all files
  48.           -c Use 16 bit CRC (XMODEM)
  49.           -e Escape control characters  (ZMODEM)
  50.           -p protect local files (ZMODEM)
  51.           -t <tenths> rx timeout seconds
  52.           -+ force append
  53.           -u convert uppercase filenames to lower case
  54.           -y Yes, clobber existing file if any
  55.           -. line fd to use
  56.           -, log protocol packets
  57.  
  58. --------------------------------------------------------------------------*/
  59. /*+:EDITS:*/
  60. /*:05-21-1990-16:00-wht@tridom-adapt ecu xfer protocols for tipwht */
  61.  
  62. #include <stdio.h>
  63. #include <signal.h>
  64. #include <setjmp.h>
  65. #include <ctype.h>
  66. #include <errno.h>
  67. #include <fcntl.h>
  68. #include "zmodem.h"
  69. #include "zlint.h"
  70.  
  71. char *strrchr();
  72.  
  73. #if defined(M_UNIX)
  74. char *fname_truncated();
  75. #endif
  76.  
  77. extern unsigned short crctab[];
  78. extern unsigned long total_data_chars_xfered; /* zcurses.c */
  79. extern int errno;
  80. extern char *sys_errlist[];
  81. extern char Attn[];        /* Attention string rx sends to tx on err */
  82. extern int Crc32;        /* Display flag indicating 32 bit CRC being received */
  83. extern int Rxcount;        /* Count of data bytes received */
  84. extern char Rxhdr[];    /* Received header */
  85. extern char Txhdr[];    /* Transmitted header */
  86. extern int Rxtimeout;    /* Tenths of seconds to wait for something */
  87. extern char s256[];
  88.  
  89. /* Max value for VMIN_COUNT is 255.  A larger value reduces system
  90. overhead but may evoke kernel bugs.  133 corresponds to an XMODEM/CRC
  91. sector */
  92. #if !defined(VMIN_COUNT)
  93. #define VMIN_COUNT 133
  94. #endif
  95. unsigned char vmin_count = VMIN_COUNT;
  96. int Readnum = VMIN_COUNT;    /* num bytes to ask for in read() from modem */
  97.  
  98. #define DEFBYTL 2000000000L    /* default rx file size */
  99. #define RETRYMAX 5
  100.  
  101. FILE *fout;
  102. char Lzmanag;        /* Local file management request */
  103. char Pathname[PATHLEN];
  104. char curr_dir[256];
  105. unsigned char linbuf[VMIN_COUNT];
  106. char s128[128];
  107. char secbuf[1025];
  108. char zconv;                /* ZMODEM file conversion request */
  109. char zmanag;            /* ZMODEM file management request */
  110. char ztrans;            /* ZMODEM file transport request */
  111. int Batch=0;
  112. int Blklen;                /* record length of received packets */
  113. int Crcflg;
  114. int Eofseen;            /* indicates cpm eof (^Z) has been received */
  115. int Filcnt=0;            /* count of number of files opened */
  116. int Filemode;            /* Unix style mode for incoming file */
  117. int Firstsec;
  118. int Lastrx;
  119. int Lleft=0;            /* number of characters in linbuf */
  120. int MakeLCPathname=1;    /* make received pathname lower case */
  121. int Nozmodem = 0;        /* If invoked as "rb" */
  122. int Rxascii=0;            /* receive files in ascii (translate) mode */
  123. int Rxbinary=0;            /* receive all files in bin mode */
  124. int Rxclob=0;            /* Clobber existing file */
  125. int Thisbinary;            /* current file is to be received in bin mode */
  126. int Twostop = 0;        /* use two stop bits */
  127. int Zctlesc;            /* Encode control characters */
  128. int Zmodem=0;            /* ZMODEM protocol requested */
  129. int Zrwindow = 1400;    /* RX window size (controls garbage count) */
  130. int tipsz_flag = 0;
  131. int skip_count = 0;        /* skipped files */
  132. int errors;
  133. int iofd = 0;
  134. int log_packets = 0;
  135. int npats = 0;
  136. int oldBlklen = -1;        /* last block length */
  137. int this_file_errors = 0;
  138. int tryzhdrtype=ZRINIT;    /* Header type to send corresponding to Last rx close */
  139. jmp_buf tohere;            /* For the interrupt on RX timeout */
  140. long Bytesleft;            /* number of bytes of incoming file left */
  141. long Modtime;            /* Unix style mod time for incoming file */
  142. long TotalToReceive = 0L;
  143. long rx_char_count = 0L;
  144. long tx_char_count = 0L;
  145. struct stat fout_stat;
  146. time_t timep[2];
  147. unsigned Baudrate;
  148. unsigned long this_file_length;
  149. int required_type = 0;
  150. char *bottom_label = (char *)0;
  151.  
  152. /*+-----------------------------------------------------------------------
  153.     arg_token(parsestr,termchars)
  154.  
  155. Get next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
  156. calls), where tokens are nonempty strings separated by runs of chars
  157. from termchars.  Writes nulls into parsestr to end tokens.
  158. termchars need not remain constant from call to call.
  159.  
  160. Treats multiple occurrences of a termchar as one delimiter (does not
  161. allow null fields).
  162. ------------------------------------------------------------------------*/
  163. #if defined(M_UNIX)
  164. static char *arg_token_static = (char *)0;
  165. char *arg_token(parsestr,termchars)
  166. char *parsestr;
  167. char *termchars;
  168. {
  169. register int first = 1;
  170. register char *termptr;
  171. register char *parseptr;
  172. char *token;
  173.  
  174.     if(parsestr == (char *)0 && arg_token_static == (char *)0)
  175.         return((char *)0);
  176.  
  177.     if(parsestr)
  178.         parseptr = parsestr;
  179.     else
  180.        parseptr = arg_token_static;
  181.  
  182.     while(*parseptr)
  183.     {
  184.         if(!strchr(termchars,*parseptr))
  185.             break;
  186.         parseptr++;
  187.     }
  188.  
  189.     if(!*parseptr)
  190.     {
  191.         arg_token_static = (char *)0;
  192.         return((char *)0);
  193.     }
  194.  
  195.     token = parseptr;
  196.     if(*token == '\'')
  197.     {
  198.         token++;
  199.         parseptr++;
  200.         while(*parseptr)
  201.         {
  202.             if(*parseptr == '\'')
  203.             {
  204.                 arg_token_static = parseptr + 1;
  205.                 *parseptr = 0;
  206.                 return(token);
  207.             }
  208.             parseptr++;
  209.         }
  210.         arg_token_static = (char *)0;
  211.         return(token);
  212.     }
  213.     while(*parseptr)
  214.     {
  215.         if(strchr(termchars,*parseptr))
  216.         {
  217.             *parseptr = 0;
  218.             arg_token_static = parseptr + 1;
  219.             while(*arg_token_static)
  220.             {
  221.                 if(!strchr(termchars,*arg_token_static))
  222.                     break;
  223.                 arg_token_static++;
  224.             }
  225.             return(token);
  226.         }
  227.         parseptr++;
  228.     }
  229.     arg_token_static = (char *)0;
  230.     return(token);
  231. }    /* end of arg_token */
  232. #endif
  233.  
  234. /*+-------------------------------------------------------------------------
  235.     fname_split(cmd,arg,arg_max_quan,&narg)
  236. --------------------------------------------------------------------------*/
  237. #if defined(M_UNIX)
  238. void
  239. fname_split(cmd,arg,arg_max_quan,narg_rtn)
  240. char *cmd;
  241. char **arg;
  242. int arg_max_quan;
  243. int *narg_rtn;
  244. {
  245. register itmp;
  246. register narg;
  247.  
  248.     for(itmp = 0; itmp < arg_max_quan; itmp++)
  249.         arg[itmp] = (char *)0;
  250.     arg[0] = arg_token(cmd,"/");
  251.  
  252.     for(narg = 1; narg < arg_max_quan; ++narg)
  253.     {
  254.         if((arg[narg] = arg_token((char *)0,"/")) == (char *)0) 
  255.             break;
  256.     }
  257.  
  258.     *narg_rtn = narg;
  259.  
  260. }    /* end of fname_split */
  261. #endif
  262.  
  263. #if defined(M_UNIX)
  264. #define MAX_COMPONENT_LEN    14
  265. #define MAX_PATH_COMPONENTS    16
  266. static char trunc_fname[257];
  267. static char *trunc_components[MAX_PATH_COMPONENTS];
  268. static int trunc_components_quan;
  269. static int trunc_absolute_path;
  270. #endif
  271.  
  272. /*+-------------------------------------------------------------------------
  273.     fname_too_long(fname) - check for any pathname component too long
  274. --------------------------------------------------------------------------*/
  275. #if defined(M_UNIX)
  276. int
  277. fname_too_long(fname)
  278. register char *fname;
  279. {
  280. register int itmp;
  281. register char **cpptr;
  282.  
  283.     if(trunc_absolute_path = (*fname == '/'))
  284.         fname++;
  285.     strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1);
  286.     fname_split(trunc_fname,trunc_components,
  287.         MAX_PATH_COMPONENTS,&trunc_components_quan);
  288.     itmp = trunc_components_quan;
  289.     cpptr = trunc_components;
  290.     while(itmp--)
  291.     {
  292.         if(strlen(*cpptr) > MAX_COMPONENT_LEN)
  293.             return(1);
  294.         cpptr++;
  295.     }
  296.     return(0);
  297. }    /* end of fname_too_long */
  298. #endif
  299.  
  300. /*+-------------------------------------------------------------------------
  301.     fname_truncated() - build truncated path last checked by fname_too_long
  302. --------------------------------------------------------------------------*/
  303. #if defined(M_UNIX)
  304. char *
  305. fname_truncated()
  306. {
  307. register int icomp;
  308. char new_fname[257];
  309. register char *cptr = new_fname;
  310.  
  311.     if(trunc_absolute_path)
  312.     {
  313.         *cptr = '/';
  314.         *(cptr + 1) = 0;
  315.     }
  316.     else
  317.         *cptr = 0;
  318.     for(icomp = 0; icomp < trunc_components_quan; icomp++)
  319.     {
  320.         if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
  321.             *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
  322.         strcat(cptr,trunc_components[icomp]);
  323.         if(icomp < trunc_components_quan - 1)
  324.             strcat(cptr,"/");
  325.     }
  326.     strcpy(trunc_fname,cptr);
  327.     return(trunc_fname);
  328.  
  329. }    /* end of fname_truncated */
  330. #endif
  331.  
  332. /*+-------------------------------------------------------------------------
  333.     substr(str,token)
  334.  
  335.   searches for token in string str returns pointer to token within
  336.   string if found,NULL otherwise
  337. --------------------------------------------------------------------------*/
  338. char *
  339. substr(str,token)
  340. register char *str,*token;
  341. {
  342. register char *ss,*tt;
  343.  
  344.     /* search for first char of token */
  345.     for(ss=str; *str; str++)
  346.         if(*str == *token)
  347.             /* compare token with substring */
  348.             for(ss=str,tt=token; ;)
  349.             {
  350.                 if(*tt == 0)
  351.                     return(str);
  352.                 if(*ss++ != *tt++)
  353.                     break;
  354.             }
  355.     return(NULL);
  356. }    /* end of substr */
  357.  
  358. /*+-------------------------------------------------------------------------
  359.     getfree()
  360.  
  361.   Routine to calculate the free bytes on the current file system ~0
  362.   means many free bytes (unknown)
  363. --------------------------------------------------------------------------*/
  364. long
  365. getfree()
  366. {
  367.     return(~0L);    /* many free bytes ... */
  368. }    /* end of getfree */
  369.  
  370. /*+-------------------------------------------------------------------------
  371.     usage(fail_reason)
  372. --------------------------------------------------------------------------*/
  373. void
  374. usage(fail_reason)
  375. char *fail_reason;
  376. {
  377.     fprintf(stderr,"%s\n",fail_reason);
  378.     exit(255);
  379. }    /* end of usage */
  380.  
  381. /*+-------------------------------------------------------------------------
  382.     SIGALRM_handler()
  383. --------------------------------------------------------------------------*/
  384. void
  385. SIGALRM_handler()
  386. {
  387.     report_tx_ind(0);
  388.     report_rx_ind(0);
  389.     longjmp(tohere,-1);
  390. }    /* end of SIGALRM_handler */
  391.  
  392. /*+-------------------------------------------------------------------------
  393.     bye_bye(sig)
  394. --------------------------------------------------------------------------*/
  395. void
  396. bye_bye(sig)
  397. int sig;
  398. {
  399.     exit(sig+128);
  400. }    /* end of bye_bye */
  401.  
  402. /*+-------------------------------------------------------------------------
  403.     cancel_transaction(sig)
  404. called by signal interrupt or terminate to clean things up
  405. --------------------------------------------------------------------------*/
  406. void
  407. cancel_transaction(sig)
  408. {
  409.     if(Zmodem)
  410.         zmputs(Attn);
  411.     send_cancel();
  412.     mode(0);
  413.     if(sig >= 0)
  414.     {
  415.         sprintf(s128,"tiprz aborted (signal %d)",sig);
  416.         report_str(s128,0);
  417.     }
  418.     report_tx_ind(0);
  419.     report_rx_ind(0);
  420.     report_uninit(0);
  421.     bye_bye(sig);
  422. }    /* end of cancel_transaction */
  423.  
  424. /*+-------------------------------------------------------------------------
  425.     sendline(c) -  send a character to DCE
  426. --------------------------------------------------------------------------*/
  427. sendline(c)
  428. char c;
  429. {
  430.     write(iofd,&c,1);
  431.     ++tx_char_count;
  432. }    /* end of sendline */
  433.  
  434. /*+-------------------------------------------------------------------------
  435.     xsendline(c)
  436. --------------------------------------------------------------------------*/
  437. xsendline(c)
  438. {
  439.     sendline(c);
  440. }    /* end of xsendline */
  441.  
  442. /*+-------------------------------------------------------------------------
  443.     flushline()
  444. --------------------------------------------------------------------------*/
  445. flushline()
  446. {
  447. }    /* end of flushline */
  448.  
  449. /*+-------------------------------------------------------------------------
  450.     purgeline() - purge the modem input queue of all characters
  451. --------------------------------------------------------------------------*/
  452. purgeline()
  453. {
  454.     Lleft = 0;
  455. #if defined(M_XENIX) || defined(M_UNIX)
  456.     ioctl(iofd,TCFLSH,0);
  457. #else
  458.     lseek(iofd,0L,2);
  459. #endif
  460. }    /* end of purgeline */
  461.  
  462. /*+-------------------------------------------------------------------------
  463.     wcreceive(argc,argp)
  464. --------------------------------------------------------------------------*/
  465. wcreceive(argc,argp)
  466. int argc;
  467. char **argp;
  468. {
  469. register c;
  470.  
  471.     if(Batch || argc==0)
  472.     {
  473.         Crcflg=1;
  474.         c=tryz();
  475.         if(Zmodem)
  476.         {
  477.             report_protocol_type("ZMODEM");
  478.             report_protocol_crc_type((Crc32) ? "/CRC32" : "/CRC16");
  479.         }
  480.         if(c)
  481.         {
  482.             if(c == ZCOMPL)
  483.                 return(OK);
  484.             if(c == ERROR)
  485.                 goto fubar;
  486.             c = rzfiles();
  487.             if(c)
  488.                 goto fubar;
  489.         } else 
  490.         {
  491.             report_protocol_type("YMODEM");
  492.             report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
  493.             for(;;)
  494.             {
  495.                 if(wcrxpn(secbuf)== ERROR)
  496.                     goto fubar;
  497.                 if(secbuf[0]==0)
  498.                     return(OK);
  499.                 if(procheader(secbuf) == ERROR)
  500.                     goto fubar;
  501.                 report_str("Receiving data",0);
  502.                 if(wcrx()==ERROR)
  503.                     goto fubar;
  504.             }
  505.         }
  506.     }
  507.     else 
  508.     {
  509.         report_protocol_type("XMODEM");
  510.         report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
  511.         Bytesleft = DEFBYTL;
  512.         Filemode = 0;
  513.         Modtime = 0L;
  514.         procheader("");
  515.         strcpy(Pathname,*argp);
  516.         if((fout=fopen(Pathname,"w")) == NULL)
  517.         {
  518.             sprintf(s128,"%-0.85s: %-0.40s",Pathname,sys_errlist[errno]);
  519.             report_str(s128,1);
  520.             goto fubar;
  521.         }
  522.  
  523.         report_file_rcv_started( Pathname,0L,Modtime,Filemode);
  524.         this_file_length = 0;
  525.         report_rxpos(0L);
  526.         report_str("Receiving data",0);
  527.         if(wcrx()==ERROR)
  528.             goto fubar;
  529.     }
  530.     return(OK);
  531. fubar:
  532.     send_cancel();
  533.     if(fout)
  534.     {
  535.         fflush(fout);
  536.         fstat(fileno(fout),&fout_stat);
  537.         report_file_byte_io((long)fout_stat.st_size);
  538.         report_file_close();
  539.         fclose(fout);
  540.     }
  541.     return(ERROR);
  542. }    /* end of wcreceive */
  543.  
  544. /*+-------------------------------------------------------------------------
  545.     wcgetsec(rxbuf,maxtime)
  546.  
  547.   Wcgetsec fetches a Ward Christensen type sector.  Returns sector
  548.   number encountered or ERROR if valid sector not received, or CAN CAN
  549.   received or WCEOT if eot sector time is timeout for first char,set to
  550.   4 seconds thereafter. NO ACK IS SENT IF SECTOR IS RECEIVED OK. Caller
  551.   must do that when he is good and ready to get next sector.
  552. --------------------------------------------------------------------------*/
  553. unsigned int
  554. wcgetsec(rxbuf,maxtime)
  555. char *rxbuf;
  556. int maxtime;
  557. {
  558. register unsigned int firstch;
  559. register unsigned short oldcrc;
  560. register unsigned char checksum;
  561. register wcj;
  562. register char *p;
  563. int sectcurr;
  564.  
  565.     for(Lastrx=errors=0; errors<RETRYMAX; errors++)
  566.     {
  567.  
  568.         firstch=readline(maxtime);
  569.         if((firstch == STX) || (firstch == SOH))
  570.         {
  571.             oldBlklen = Blklen;
  572.             if(firstch == STX)
  573.                 Blklen=1024;
  574.             else
  575.                 Blklen=128;
  576.             if(oldBlklen != Blklen)
  577.                 report_rxblklen(Blklen);
  578.  
  579.             sectcurr=readline(1);
  580.             if((sectcurr + (oldcrc=readline(1))) == 0xFF)
  581.             {
  582.                 oldcrc=checksum=0;
  583.                 for(p=rxbuf,wcj=Blklen; --wcj>=0; )
  584.                 {
  585.                     if((firstch=readline(1)) < 0)
  586.                         goto bilge;
  587.                     oldcrc=updcrc(firstch,oldcrc);
  588.                     checksum += (*p++ = firstch);
  589.                 }
  590.                 if((firstch=readline(1)) < 0)
  591.                     goto bilge;
  592.                 if(Crcflg)
  593.                 {
  594.                     oldcrc=updcrc(firstch,oldcrc);
  595.                     if((firstch=readline(1)) < 0)
  596.                         goto bilge;
  597.                     oldcrc=updcrc(firstch,oldcrc);
  598.                     if(oldcrc)
  599.                     {
  600.                         sprintf(s128,"CRC error = 0x%04x",oldcrc);
  601.                         report_str(s128,1);
  602.                     }
  603.                     else 
  604.                     {
  605.                         Firstsec=0;
  606.                         return(sectcurr);
  607.                     }
  608.                 }
  609.                 else if((checksum-firstch)==0)
  610.                 {
  611.                     Firstsec=0;
  612.                     return(sectcurr);
  613.                 }
  614.                 else
  615.                     report_str("checksum error",1);
  616.             }
  617.             else
  618.             {
  619.                 report_last_txhdr("Noise",0);
  620.                 sprintf(s128,"Sector garbled 0x%x 0x%x",sectcurr,oldcrc);
  621.                 report_str(s128,1);
  622.             }
  623.         }
  624.         /* make sure eot really is eot and not just mixmash */
  625. #if defined(NFGVMIN)
  626.         else if(firstch==EOT && readline(1)==TIMEOUT)
  627.             return(WCEOT);
  628. #else
  629.         else if(firstch==EOT && Lleft==0)
  630.             return(WCEOT);
  631. #endif
  632.         else if(firstch==EOT)
  633.         {
  634.             report_str("Noisy EOT",2);
  635.         }
  636.         else if(firstch==CAN)
  637.         {
  638.             if(Lastrx==CAN)
  639.             {
  640.                 report_str("Sender CANcelled",1);
  641.                 report_last_rxhdr("CAN",1);
  642.                 return(ERROR);
  643.             } else 
  644.             {
  645.                 Lastrx=CAN;
  646.                 continue;
  647.             }
  648.         }
  649.         else if(firstch==TIMEOUT)
  650.         {
  651.             if(Firstsec)
  652.                 goto humbug;
  653. bilge:
  654.             report_str("Timeout",1);
  655.         }
  656.         else
  657.         {
  658.             sprintf(s128,"Got 0x%02x sector header",firstch);
  659.             report_str(s128,1);
  660.         }
  661.  
  662. humbug:
  663.         Lastrx=0;
  664.         while(readline(1)!=TIMEOUT)
  665.             ;
  666.         if(Firstsec)
  667.         {
  668.             sendline(Crcflg?WANTCRC:NAK);
  669.             report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  670.             Lleft=0;    /* Do read next time ... */
  671.         } else 
  672.         {
  673.             maxtime=40;
  674.             sendline(NAK);
  675.             report_last_txhdr("NAK",1);
  676.             Lleft=0;    /* Do read next time ... */
  677.         }
  678.     }
  679.     /* try to stop the bubble machine. */
  680.     send_cancel();
  681.     return(ERROR);
  682. }    /* end of wcgetsec */
  683.  
  684. /*+-------------------------------------------------------------------------
  685.     wcrxpn(rpn)
  686.  
  687.   Fetch a pathname from the other end.  Length is indeterminate as long
  688.   as less than Blklen.  During YMODEM xfers, a null string represents no
  689.   more files.
  690. --------------------------------------------------------------------------*/
  691. wcrxpn(rpn)
  692. char *rpn;    /* receive a pathname */
  693. {
  694. register c;
  695.  
  696. #if defined(NFGVMIN)
  697.     readline(1);
  698. #else
  699.     purgeline();
  700. #endif
  701.  
  702. et_tu:
  703.     Firstsec=1;
  704.     Eofseen=0;
  705.     sendline(Crcflg?WANTCRC:NAK);
  706.     report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  707.     Lleft=0;    /* Do read next time ... */
  708.     while((c = wcgetsec(rpn,100)) != 0)
  709.     {
  710.         if(c == WCEOT)
  711.         {
  712.             sprintf(s128,"Pathname fetch returned %d",c);
  713.             report_str(s128,1);
  714.             sendline(ACK);
  715.             report_last_txhdr("ACK",0);
  716.             Lleft=0;    /* Do read next time ... */
  717.             readline(1);
  718.             goto et_tu;
  719.         }
  720.         return(ERROR);
  721.     }
  722.     sendline(ACK);
  723.     report_last_txhdr("ACK",0);
  724.     return(OK);
  725. }    /* end of wcrxpn */
  726.  
  727. /*+-------------------------------------------------------------------------
  728.     write_sec_to_disk(buf,n)
  729.  
  730.   Putsec writes the n characters of buf to receive file fout.  If not in
  731.   binary mode, carriage returns, and all characters starting with CPMEOF
  732.   are discarded.
  733. --------------------------------------------------------------------------*/
  734. write_sec_to_disk(buf,n)
  735. char *buf;
  736. register n;
  737. {
  738. register char *p;
  739.  
  740.     if(n == 0)
  741.         return(OK);
  742.     if(Thisbinary)
  743.     {
  744.         for(p=buf; --n>=0; )
  745.             putc( *p++,fout);
  746.     }
  747.     else 
  748.     {
  749.         if(Eofseen)
  750.             return(OK);
  751.         for(p=buf; --n>=0; ++p )
  752.         {
  753.             if( *p == '\r')
  754.                 continue;
  755.             if(*p == CPMEOF)
  756.             {
  757.                 Eofseen=1;
  758.                 fflush(fout);
  759.                 fstat(fileno(fout),&fout_stat);
  760.                 report_rxpos(fout_stat.st_size);
  761.                 return(OK);
  762.             }
  763.             putc(*p ,fout);
  764.         }
  765.     }
  766.     fflush(fout);
  767.     fstat(fileno(fout),&fout_stat);
  768.     report_rxpos(fout_stat.st_size);
  769.     if(this_file_length != 0)
  770.     {
  771.         sprintf(s128,"Receiving data (%u%% complete)",
  772.             (unsigned int)(
  773.             ((unsigned long)fout_stat.st_size * (unsigned long)100)
  774.             / this_file_length));
  775.         report_str(s128,0);
  776.     }
  777.     return(OK);
  778. }    /* end of write_sec_to_disk */
  779.  
  780. /*+-------------------------------------------------------------------------
  781.     wcrx() - receive an X/YMODEM sector
  782.  
  783.   Adapted from CMODEM13.C,written by Jack M.  Wierda and Roderick W. Hart
  784. --------------------------------------------------------------------------*/
  785. int
  786. wcrx()
  787. {
  788. register unsigned int sectnum,sectcurr;
  789. register unsigned char sendchar;
  790. register unsigned char *p;
  791. int cblklen;            /* bytes to dump this block */
  792.  
  793.     Firstsec=1;
  794.     sectnum=0;
  795.     Eofseen=0;
  796.     sendchar=Crcflg ? WANTCRC : NAK;
  797.     report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  798.  
  799.     for(;;)
  800.     {
  801.         sendline(sendchar);    /* send it now,we're ready! */
  802.         if(sendchar == ACK)
  803.             report_last_txhdr("ACK",0);
  804.         Lleft=0;    /* Do read next time ... */
  805.         sectcurr=wcgetsec(secbuf,(sectnum&0177)?50:130);
  806.         sprintf(s128,"Block %d received",sectnum);
  807.         report_last_rxhdr(s128,0);
  808.         fstat(fileno(fout),&fout_stat);
  809.         report_rxpos(fout_stat.st_size);
  810.         if(sectcurr == (sectnum+1 & 0xFF))
  811.         {
  812.             sectnum++;
  813.             cblklen = Bytesleft>Blklen ? Blklen : Bytesleft;
  814.             if(write_sec_to_disk(secbuf,cblklen) == ERROR)
  815.                 return(ERROR);
  816.             if((Bytesleft-=cblklen) < 0)
  817.                 Bytesleft = 0;
  818.             sendchar=ACK;
  819.         }
  820.         else if(sectcurr == sectnum)
  821.         {
  822.             report_str("Received duplicate Sector",-1);
  823.             sendchar = ACK;
  824.         }
  825.         else if(sectcurr == WCEOT)
  826.         {
  827.             if(close_and_report())
  828.                 return(ERROR);
  829.             sendline(ACK);
  830.             report_last_txhdr("ACK",0);
  831.             Lleft=0;    /* Do read next time ... */
  832.             return(OK);
  833.         }
  834.         else if(sectcurr==ERROR)
  835.             return(ERROR);
  836.         else 
  837.         {
  838.             report_str( "Sync Error",1);
  839.             return(ERROR);
  840.         }
  841.     }
  842. }    /* end of wcrx */
  843.  
  844. /*+-------------------------------------------------------------------------
  845.     readline(timeout)
  846.  
  847.   read one or more characters timeout is in tenths of seconds
  848. --------------------------------------------------------------------------*/
  849. readline(timeout)
  850. int timeout;
  851. {
  852. register n;
  853. static unsigned char *cdq;    /* pointer for removing chars from linbuf */
  854.  
  855.     if(--Lleft >= 0)
  856.         return(*cdq++);
  857.  
  858.     n = timeout/10;
  859.     if(n < 2)
  860.         n = 3;
  861.     if(setjmp(tohere))
  862.     {
  863.         Lleft = 0;
  864.         return(TIMEOUT);
  865.     }
  866.     signal(SIGALRM,SIGALRM_handler);
  867.     alarm(n);
  868.     Lleft = read(iofd,cdq = linbuf,Readnum);
  869.     alarm(0);
  870.     rx_char_count += Lleft;
  871.  
  872.     if(Lleft < 1)
  873.         return(TIMEOUT);
  874.  
  875.     --Lleft;
  876.     return(*cdq++);
  877.  
  878. }    /* end of readline */
  879.  
  880. /*+-------------------------------------------------------------------------
  881.     mkdir(dpath,dmode)
  882.  Directory-creating routines from Public Domain TAR by John Gilmore
  883.  Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
  884. --------------------------------------------------------------------------*/
  885. #if defined(MD)
  886. #if (MD != 2)
  887. #define    TERM_SIGNAL(status)        ((status) & 0x7F)
  888. #define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  889. #define TERM_VALUE(status)        ((status) >> 8)
  890. mkdir(dpath,dmode)
  891. char *dpath;
  892. int dmode;
  893. {
  894. int cpid,status;
  895. struct stat statbuf;
  896.  
  897.     if(stat(dpath,&statbuf) == 0)
  898.     {
  899.         errno = EEXIST;        /* Stat worked,so it already exists */
  900.         return(-1);
  901.     }
  902.  
  903.     /* If stat fails for a reason other than non-existence,return error */
  904.     if(errno != ENOENT)
  905.         return(-1);
  906.  
  907.     switch(cpid = fork())
  908.     {
  909.  
  910.     case -1:            /* Error in fork() */
  911.         return(-1);        /* Errno is set already */
  912.  
  913.     case 0:                /* Child process */
  914.         /*
  915.          * Cheap hack to set mode of new directory.  Since this
  916.          * child process is going away anyway,we zap its umask.
  917.          * FIXME,this won't suffice to set SUID,SGID,etc. on this
  918.          * directory.  Does anybody care?
  919.          */
  920.         status = umask(0);    /* Get current umask */
  921.         status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
  922.         execl("/bin/mkdir","mkdir",dpath,(char *)0);
  923.         _exit(-1);        /* Can't exec /bin/mkdir */
  924.  
  925.     default:            /* Parent process */
  926.         while(cpid != wait(&status)) ;    /* Wait for kid to finish */
  927.     }
  928.  
  929.     if(TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0)
  930.     {
  931.         errno = EIO;        /* We don't know why,but */
  932.         return(-1);        /* /bin/mkdir failed */
  933.     }
  934.  
  935.     return(0);
  936. }    /* end of mkdir */
  937. #endif /* MD != 2 */
  938. #endif /* if defined(MD) */
  939.  
  940. /*+-------------------------------------------------------------------------
  941.     make_dirs(pathname)
  942.  
  943.   Directory-creating routines from Public Domain TAR by John Gilmore
  944.   After a file/link/symlink/dir creation has failed, see if it's because
  945.   some required directory was not present, and if so, create all
  946.   required dirs.
  947. --------------------------------------------------------------------------*/
  948. #if defined(MD)
  949. make_dirs(pathname)
  950. register char *pathname;
  951. {
  952.     register char *p;            /* Points into path */
  953.     int madeone = 0;            /* Did we do anything yet? */
  954.     int save_errno = errno;        /* Remember caller's errno */
  955.  
  956.     if(errno != ENOENT)
  957.         return(0);        /* Not our problem */
  958.  
  959.     for(p = strchr(pathname,'/'); p != NULL; p = strchr(p+1,'/'))
  960.     {
  961.         /* Avoid mkdir of empty string,if leading or double '/' */
  962.         if(p == pathname || p[-1] == '/')
  963.             continue;
  964.         /* Avoid mkdir where last part of path is '.' */
  965.         if(p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  966.             continue;
  967.         *p = 0;                /* Truncate the path there */
  968.         if( !mkdir(pathname,0777))    /* Try to create it as a dir */
  969.         {
  970.             sprintf(s128,"Made directory %s",pathname);
  971.             report_str(s128,-1);
  972.             madeone++;        /* Remember if we made one */
  973.             *p = '/';
  974.             continue;
  975.         }
  976.         *p = '/';
  977.         if(errno == EEXIST)        /* Directory already exists */
  978.             continue;
  979.         /*
  980.          * Some other error in the mkdir.  We return to the caller.
  981.          */
  982.         break;
  983.     }
  984.     errno = save_errno;        /* Restore caller's errno */
  985.     return(madeone);            /* Tell them to retry if we made one */
  986. }    /* end of make_dirs */
  987. #endif /* MD */
  988.  
  989. /*+-------------------------------------------------------------------------
  990.     uncaps(str) - make string str lower case
  991. --------------------------------------------------------------------------*/
  992. void
  993. uncaps(str)
  994. register char *str;
  995. {
  996. register int itmp;
  997.  
  998.     while(itmp = *str)
  999.     {
  1000.         if(isupper(itmp))
  1001.             *str = tolower(itmp);
  1002.         str++;
  1003.     }
  1004. }    /* end of uncaps */
  1005.  
  1006. /*+-------------------------------------------------------------------------
  1007.     isanylc(str) - returns 1 if string str has any lower case letters
  1008. --------------------------------------------------------------------------*/
  1009. int
  1010. isanylc(str)
  1011. register char *str;
  1012. {
  1013.     while(*str)
  1014.     {
  1015.         if(islower(*str))
  1016.             return(1);
  1017.         str++;
  1018.     }
  1019.     return(0);
  1020. }    /* end of isanylc */
  1021.  
  1022. /*+-------------------------------------------------------------------------
  1023.     procheader(name) - process incoming file information header
  1024. --------------------------------------------------------------------------*/
  1025. int
  1026. procheader(name)
  1027. char *name;
  1028. {
  1029. register char *openmode,*p,**pp;
  1030. #if defined(M_UNIX)
  1031. char *cptr;
  1032. char name2[PATHLEN];
  1033. #endif
  1034.  
  1035.     /* set default parameters and overrides */
  1036.     openmode = "w";
  1037.     Thisbinary = (!Rxascii) || Rxbinary;
  1038.     if(Lzmanag)
  1039.         zmanag = Lzmanag;
  1040.  
  1041.     /*
  1042.      *  Process ZMODEM remote file management requests
  1043.      */
  1044.     if(!Rxbinary && zconv == ZCNL)    /* Remote ASCII override */
  1045.         Thisbinary = 0;
  1046.     if(zconv == ZCBIN)    /* Remote Binary override */
  1047.         Thisbinary = 1;
  1048.     else if(zmanag == ZMAPND)
  1049.         openmode = "a";
  1050.  
  1051.     report_xfer_mode(Thisbinary ? "BINARY" : "ASCII");
  1052.     this_file_errors = 0;
  1053.  
  1054.     Bytesleft = DEFBYTL;
  1055.     Filemode = 0;
  1056.     Modtime = 0L;
  1057.     this_file_length = 0;
  1058.  
  1059.     if(strlen(name))
  1060.         p = name + 1 + strlen(name);
  1061.     else
  1062.         p = name;
  1063.  
  1064.     if(*p)
  1065.     {    /* file coming from Unix or DOS system */
  1066.     int sscanf_count;
  1067.     int SerialNumber;
  1068.     int Filesleft;
  1069.     long TotalLeft;
  1070.  
  1071.         sscanf_count = sscanf(p,"%ld%lo%o%d&d&ld",
  1072.             &Bytesleft,&Modtime,&Filemode,&SerialNumber,
  1073.             &Filesleft,&TotalLeft);
  1074.  
  1075.         switch(sscanf_count)
  1076.         {
  1077.         case 6:    /* TotalLeft */
  1078.             if(!TotalToReceive)
  1079.                 TotalToReceive = TotalLeft;
  1080.         case 5:    /* Filesleft */
  1081.             if(!npats)
  1082.                 npats = Filesleft;
  1083.         default:
  1084.             break;
  1085.         }
  1086.  
  1087.         if((zmanag & ZMMASK) == ZMNEW)
  1088.         {
  1089.             if(stat(name,&fout_stat) == 0)            /* if file accessable ... */
  1090.             {
  1091.                 if(Modtime <= fout_stat.st_mtime)    /* ... and not older */
  1092.                 {
  1093.                     sprintf(s128,"RECEIVE skipped: %s (same or later date)",
  1094.                         name);
  1095.                     report_str(s128 + 8,-1);
  1096.                     skip_count++;
  1097.                     report_error_count();
  1098.                     return(ERROR);
  1099.                 }
  1100.             }
  1101.         }
  1102.         /* Check for existing file */
  1103.         else if(!Rxclob && ((zmanag & ZMMASK) != ZMCLOB) &&
  1104.             (fout=fopen(name,"r")))
  1105.         {
  1106.             fclose(fout);
  1107.             sprintf(s128,"RECEIVE skipped: %s (already exists)",name);
  1108.             report_str(s128 + 8,-1);
  1109.             skip_count++;
  1110.             report_error_count();
  1111.             return(ERROR);
  1112.         }
  1113.  
  1114.         if(Filemode & UNIXFILE)
  1115.             ++Thisbinary;
  1116.         ++Filcnt;
  1117.  
  1118.         report_file_rcv_started( name,
  1119.             (Bytesleft != DEFBYTL) ? Bytesleft : 0,Modtime,Filemode);
  1120.         report_rxpos(0L);
  1121.         report_str("",0);    /* get rid of End of File */
  1122.         if(Bytesleft != DEFBYTL)
  1123.         {
  1124.             long min_100;
  1125.             this_file_length = Bytesleft;
  1126.             min_100 = 2L + (((Bytesleft * 11L)) * 10L) / (Baudrate * 6L);
  1127.             sprintf(s128,"Receive time this file ~= %2lu:%02lu",
  1128.                 min_100 / 100,((min_100 % 100) * 60L) / 100L);
  1129.             if(TotalToReceive)
  1130.             {
  1131.                 min_100 = 2L +
  1132.                     (((TotalToReceive * 11L)) * 10L) / (Baudrate * 6L);
  1133.                 if(Baudrate > 4800)
  1134.                 {
  1135.                     min_100 *= 13;
  1136.                     min_100 /= 9;    /* yech ... empirical */
  1137.                 }
  1138.                 sprintf(&s128[strlen(s128)],", transaction ~= %2lu:%02lu",
  1139.                     min_100 / 100,((min_100 % 100) * 60L) / 100L);
  1140.             }
  1141.             report_transaction(s128);
  1142.             sprintf(s128,"Receiving data (%d%% complete)",(int)0);
  1143.             report_str(s128,0);
  1144.         }
  1145.     }
  1146.     else 
  1147.     {        /* File coming from CP/M system */
  1148.     long now;
  1149.         for(p=name; *p; ++p)        /* change / to _ */
  1150.         {
  1151.             if( *p == '/')
  1152.                 *p = '_';
  1153.         }
  1154.  
  1155.         if( *--p == '.')        /* zap trailing period */
  1156.             *p = 0;
  1157.         time(&now);
  1158.         report_file_rcv_started( name,
  1159.             (Bytesleft != DEFBYTL) ? Bytesleft : 0,now,0);
  1160.     }
  1161.  
  1162.     if(!Zmodem && MakeLCPathname && !isanylc(name) && !(Filemode&UNIXFILE))
  1163.         uncaps(name);
  1164.  
  1165.     strcpy(Pathname,name);
  1166.     report_xfer_mode(Thisbinary?"BINARY":"ASCII");
  1167.     fout = fopen(name,openmode);
  1168. #if defined(MD)
  1169.     if( !fout)
  1170.         if(make_dirs(name))
  1171.             fout = fopen(name,openmode);
  1172. #endif
  1173.     if( !fout)
  1174.         return(ERROR);
  1175.     this_file_errors = 0;
  1176.     return(OK);
  1177. }    /* end of procheader */
  1178.  
  1179. /*+-------------------------------------------------------------------------
  1180.     send_cancel() - send cancel string
  1181. --------------------------------------------------------------------------*/
  1182. send_cancel()
  1183. {
  1184. static char canistr[] = 
  1185. {
  1186.     24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1187. };
  1188. register char *cptr = canistr;
  1189.  
  1190.     report_str("",0);
  1191.     report_last_txhdr("^X CAN",1);
  1192.     while(*cptr)
  1193.         sendline(*cptr++);
  1194.     Lleft=0;
  1195. }    /* end of send_cancel */
  1196.  
  1197. /*+-------------------------------------------------------------------------
  1198.     tryz()
  1199.  
  1200.   Initialize for Zmodem receive attempt, try to activate Zmodem sender
  1201.   Handles ZSINIT frame
  1202.   Return ZFILE if Zmodem filename received,-1 on error,
  1203.          ZCOMPL if transaction finished, else 0
  1204. --------------------------------------------------------------------------*/
  1205. int
  1206. tryz()
  1207. {
  1208. register c,n;
  1209.  
  1210.     if(Nozmodem)        /* Check for "rb" program name */
  1211.         return(0);
  1212.  
  1213.     for(n=Zmodem?15:5; --n>=0; )
  1214.     {
  1215.         /* Set buffer length (0) and capability flags */
  1216.         stohdr(0L);
  1217. #if defined(CANBREAK)
  1218.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
  1219. #else
  1220.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
  1221. #endif
  1222.         if(Zctlesc)
  1223.             Txhdr[ZF0] |= TESCCTL;
  1224.         zshhdr(tryzhdrtype,Txhdr);
  1225.         if(tryzhdrtype == ZSKIP)    /* Don't skip too far */
  1226.             tryzhdrtype = ZRINIT;    /* CAF 8-21-87 */
  1227. again:
  1228.         switch(zgethdr(Rxhdr,0))
  1229.         {
  1230.         case ZRQINIT:
  1231.             continue;
  1232.         case ZEOF:
  1233.             continue;
  1234.         case TIMEOUT:
  1235.             continue;
  1236.         case ZFILE:
  1237.             zconv = Rxhdr[ZF0];
  1238.             zmanag = Rxhdr[ZF1];
  1239.             ztrans = Rxhdr[ZF2];
  1240.  
  1241.             strcpy(s128,"Transfer: ");
  1242.             switch(zmanag & ZMMASK)
  1243.             {
  1244.             case 0:
  1245.                 strcat(s128,"if destination nonexistent");
  1246.                 break;
  1247.             case ZMAPND:    /* Append contents to existing file (if any) */
  1248.                 strcat(s128,"append to destination");
  1249.                 break;
  1250.             case ZMCLOB:    /* Replace existing file */
  1251.                 strcat(s128,"absolute (overwrite)");
  1252.                 break;
  1253.             case ZMNEW:
  1254.                 strcat(s128,"if source newer");
  1255.                 break;
  1256.             default:
  1257.                 sprintf(s128 + strlen(s128),
  1258.                     "absolute (%02x)",zmanag & ZMMASK);
  1259.                 break;
  1260.             }
  1261.             report_str(s128,2);
  1262.  
  1263.             tryzhdrtype = ZRINIT;
  1264.             c = zrdata(secbuf,1024);
  1265.             mode(3);
  1266.             if(c == GOTCRCW)
  1267.                 return(ZFILE);
  1268.             zshhdr(ZNAK,Txhdr);
  1269.             goto again;
  1270.         case ZSINIT:
  1271.             Zctlesc = TESCCTL & Rxhdr[ZF0];
  1272.             if(zrdata(Attn,ZATTNLEN) == GOTCRCW)
  1273.             {
  1274.                 stohdr(1L);
  1275.                 zshhdr(ZACK,Txhdr);
  1276.                 report_str("",-1);
  1277.                 goto again;
  1278.             }
  1279.             zshhdr(ZNAK,Txhdr);
  1280.             goto again;
  1281.         case ZFREECNT:
  1282.             stohdr(getfree());
  1283.             zshhdr(ZACK,Txhdr);
  1284.             report_str("",-1);
  1285.             goto again;
  1286.         case ZCOMMAND:
  1287.             if(zrdata(secbuf,1024) == GOTCRCW)
  1288.             {
  1289.                 stohdr(-1L);
  1290.                 purgeline();    /* dump impatient questions */
  1291.                 while(errors < 20)
  1292.                 {
  1293.                     zshhdr(ZCOMPL,Txhdr);
  1294.                     if(zgethdr(Rxhdr,1) == ZFIN)
  1295.                         break;
  1296.                 }
  1297.                 send_ZFIN_and_exit();
  1298.                 return(ZCOMPL);
  1299.             }
  1300.             zshhdr(ZNAK,Txhdr);
  1301.             goto again;
  1302.         case ZCOMPL:
  1303.             goto again;
  1304.         default:
  1305.             continue;
  1306.         case ZFIN:
  1307.             send_ZFIN_and_exit();
  1308.             return(ZCOMPL);
  1309.         case ZCAN:
  1310.             return(ERROR);
  1311.         }
  1312.     }
  1313.     return(0);
  1314. }    /* end of tryz */
  1315.  
  1316. /*+-------------------------------------------------------------------------
  1317.     rzfile() - receive a file with ZMODEM protocol
  1318.  
  1319.   assumes file name frame is in secbuf
  1320. --------------------------------------------------------------------------*/
  1321. rzfile()
  1322. {
  1323. register c,n;
  1324. long rxbytes;
  1325.  
  1326.     Eofseen=0;
  1327.     if(procheader(secbuf) == ERROR)
  1328.     {
  1329.         return(tryzhdrtype = ZSKIP);
  1330.     }
  1331.  
  1332.     n = 20;
  1333.     rxbytes = 0l;
  1334.  
  1335.     for(;;)
  1336.     {
  1337.         stohdr(rxbytes);
  1338.         zshhdr(ZRPOS,Txhdr);
  1339.         if(rxbytes)
  1340.             report_str("Sending ZRPOS",1);
  1341. nxthdr:
  1342.         switch(c = zgethdr(Rxhdr,0))
  1343.         {
  1344.         default:
  1345.             sprintf(s128,"zgethdr returned %02x",c);
  1346.             report_str(s128,1);
  1347.             return(ERROR);
  1348.         case ZNAK:
  1349.         case TIMEOUT:
  1350.             if( --n < 0)
  1351.             {
  1352.                 sprintf(s128,"zgethdr returned %02x",c);
  1353.                 report_str(s128,1);
  1354.                 return(ERROR);
  1355.             }
  1356.         case ZFILE:
  1357.             zrdata(secbuf,1024);
  1358.             continue;
  1359.         case ZEOF:
  1360.             if(rclhdr(Rxhdr) != rxbytes)
  1361.             {
  1362.                 /*
  1363.                  * Ignore eof if it's at wrong place - force
  1364.                  *  a timeout because the eof might have gone
  1365.                  *  out before we sent our zrpos.
  1366.                  */
  1367.                 errors = 0;
  1368.                 goto nxthdr;
  1369.             }
  1370.             if(close_and_report())
  1371.             {
  1372.                 tryzhdrtype = ZFERR;
  1373.                 return(ERROR);
  1374.             }
  1375.             report_str("End of file",0);
  1376.             return(c);
  1377.         case ERROR:    /* Too much garbage in header search error */
  1378.             if( --n < 0)
  1379.             {
  1380.                 sprintf(s128,"zgethdr returned %02x",c);
  1381.                 report_str(s128,1);
  1382.                 return(ERROR);
  1383.             }
  1384.             zmputs(Attn);
  1385.             continue;
  1386.         case ZSKIP:
  1387.             close_and_report();
  1388.             sprintf(s128,"rzfile: Sender SKIPPED file");
  1389.             report_str(s128,1);
  1390.             return(c);
  1391.         case ZDATA:
  1392.             if(rclhdr(Rxhdr) != rxbytes)
  1393.             {
  1394.                 if( --n < 0)
  1395.                 {
  1396.                     return(ERROR);
  1397.                 }
  1398.                 zmputs(Attn);
  1399.                 continue;
  1400.             }
  1401. moredata:
  1402.             switch(c = zrdata(secbuf,1024))
  1403.             {
  1404.             case ZCAN:
  1405.                 sprintf(s128,"zgethdr returned %02x",c);
  1406.                 report_str(s128,1);
  1407.                 return(ERROR);
  1408.             case ERROR:    /* CRC error */
  1409.                 if( --n < 0)
  1410.                 {
  1411.                     sprintf(s128,"zgethdr returned %02x",c);
  1412.                     report_str(s128,1);
  1413.                     return(ERROR);
  1414.                 }
  1415.                 zmputs(Attn);
  1416.                 continue;
  1417.             case TIMEOUT:
  1418.                 if( --n < 0)
  1419.                 {
  1420.                     sprintf(s128,"zgethdr returned %02x",c);
  1421.                     report_str(s128,1);
  1422.                     return(ERROR);
  1423.                 }
  1424.                 continue;
  1425.             case GOTCRCW:
  1426.                 n = 20;
  1427.                 write_sec_to_disk(secbuf,Rxcount);
  1428.                 rxbytes += Rxcount;
  1429.                 stohdr(rxbytes);
  1430.                 zshhdr(ZACK,Txhdr);
  1431.                 report_str("",-1);
  1432.                 sendline(XON);
  1433.                 goto nxthdr;
  1434.             case GOTCRCQ:
  1435.                 n = 20;
  1436.                 write_sec_to_disk(secbuf,Rxcount);
  1437.                 rxbytes += Rxcount;
  1438.                 stohdr(rxbytes);
  1439.                 zshhdr(ZACK,Txhdr);
  1440.                 report_str("",-1);
  1441.                 goto moredata;
  1442.             case GOTCRCG:
  1443.                 n = 20;
  1444.                 write_sec_to_disk(secbuf,Rxcount);
  1445.                 rxbytes += Rxcount;
  1446.                 goto moredata;
  1447.             case GOTCRCE:
  1448.                 n = 20;
  1449.                 write_sec_to_disk(secbuf,Rxcount);
  1450.                 rxbytes += Rxcount;
  1451.                 goto nxthdr;
  1452.             }
  1453.         }
  1454.     }
  1455. }    /* end of rzfile */
  1456.  
  1457. /*+-------------------------------------------------------------------------
  1458.     rzfiles() - receive file(s) with ZMODEM protocol
  1459. --------------------------------------------------------------------------*/
  1460. rzfiles()
  1461. {
  1462. register c;
  1463.  
  1464.     for(;;)
  1465.     {
  1466.         switch(c = rzfile())
  1467.         {
  1468.         case ZEOF:
  1469.         case ZSKIP:
  1470.             switch(tryz())
  1471.             {
  1472.             case ZCOMPL:
  1473.                 return(OK);
  1474.             default:
  1475.                 return(ERROR);
  1476.             case ZFILE:
  1477.                 break;
  1478.             }
  1479.             continue;
  1480.         default:
  1481.             return(c);
  1482.         case ERROR:
  1483.             return(ERROR);
  1484.         }
  1485.     }
  1486. }    /* end of rzfiles */
  1487.  
  1488. /*+-------------------------------------------------------------------------
  1489.     close_and_report() - close the received file, set mod time and chmod
  1490. (specifically exclude set uid and gid from chmod)
  1491. --------------------------------------------------------------------------*/
  1492. close_and_report()
  1493. {
  1494.     fflush(fout);
  1495.     fstat(fileno(fout),&fout_stat);
  1496.     report_file_byte_io((long)fout_stat.st_size);
  1497.     report_file_close();
  1498.  
  1499.     if(fclose(fout)==ERROR)
  1500.         return(ERROR);
  1501.  
  1502.     if(Modtime)
  1503.     {
  1504.         timep[0] = time(NULL);
  1505.         timep[1] = Modtime;
  1506.         utime(Pathname,timep);
  1507.     }
  1508.  
  1509.     if((Filemode & S_IFMT) == S_IFREG)
  1510.     {
  1511.         Filemode &= ~(S_ISUID | S_ISGID);
  1512.         chmod(Pathname,(07777 & Filemode));
  1513.     }
  1514.  
  1515.     return(OK);
  1516.  
  1517. }    /* end of close_and_report */
  1518.  
  1519. /*+-------------------------------------------------------------------------
  1520.     send_ZFIN_and_exit() - send ZFIN packet and wait for "OO" ack
  1521. --------------------------------------------------------------------------*/
  1522. send_ZFIN_and_exit()
  1523. {
  1524. register n;
  1525.  
  1526.     Readnum = 1;
  1527.     stohdr(0L);
  1528.     for(n = 0; n < 4; n++)
  1529.     {
  1530.         purgeline();
  1531.         zshhdr(ZFIN,Txhdr);
  1532.         switch(readline(100))
  1533.         {
  1534.         case 'O':
  1535.             readline(1);    /* Discard 2nd 'O' */
  1536.             return;
  1537.         case RCDO:
  1538.             return;
  1539.         case TIMEOUT:
  1540.         default:
  1541.             break;
  1542.         }
  1543.     }
  1544. }    /* end of send_ZFIN_and_exit */
  1545.  
  1546. /*+-------------------------------------------------------------------------
  1547.     sys2(shellcmd) - extipte shell command
  1548.  
  1549.  Strip leading ! if present
  1550. --------------------------------------------------------------------------*/
  1551. sys2(shellcmd)
  1552. register char *shellcmd;
  1553. {
  1554.     if(*shellcmd == '!')
  1555.         ++shellcmd;
  1556.     return(system(shellcmd));
  1557. } /* end of sys2 */
  1558.  
  1559. /*+-------------------------------------------------------------------------
  1560.     main(argc,argv,envp)
  1561. --------------------------------------------------------------------------*/
  1562. main(argc,argv,envp)
  1563. int argc;
  1564. char **argv;
  1565. char **envp;
  1566. {
  1567. register char *cp;
  1568. char **patts;
  1569. char *getenv();
  1570. int exitcode = 0;
  1571. char **gargv = argv;
  1572. int gargc = argc;
  1573.  
  1574.     signal(SIGINT,bye_bye);
  1575.     signal(SIGTERM,bye_bye);
  1576.  
  1577.     get_curr_dir(curr_dir,sizeof(curr_dir));
  1578.  
  1579.     Rxtimeout = 100;
  1580.  
  1581.     npats = 0;
  1582.     while(--argc)
  1583.     {
  1584.         cp = *++argv;
  1585.         if(*cp == '-')
  1586.         {
  1587.             while( *++cp)
  1588.             {
  1589.                 switch(*cp)
  1590.                 {
  1591.                 case 'X':
  1592.                     required_type = 1;
  1593.                     Batch = 0;
  1594.                     break;
  1595.                 case 'Y':
  1596.                     required_type = 1;
  1597.                     Nozmodem = 1;
  1598.                     Batch = 1;
  1599.                     break;
  1600.                 case 'Z':
  1601.                     required_type = 1;
  1602.                     Nozmodem = 0;
  1603.                     Batch = 1;
  1604.                     break;
  1605.                 case '+':
  1606.                     Lzmanag = ZMAPND;
  1607.                     break;
  1608.                 case 'a':
  1609.                     Rxascii=1;
  1610.                     break;
  1611.                 case 'b':
  1612.                     Rxbinary=1;
  1613.                     break;
  1614.                 case 'c':
  1615.                     Crcflg=1;
  1616.                     break;
  1617.                 case 'e':
  1618.                     Zctlesc = 1;
  1619.                     break;
  1620.                 case 'p':
  1621.                     Lzmanag = ZMPROT;
  1622.                     break;
  1623.                 case ',':
  1624.                     log_packets = 1;
  1625.                     break;
  1626.                 case '.':
  1627.                     if(--argc < 1)
  1628.                     {
  1629.                         usage("no iofd after -.");
  1630.                     }
  1631.                     iofd = atoi(*++argv);
  1632.                     break;
  1633.                 case 't':
  1634.                     if(--argc < 1)
  1635.                     {
  1636.                         usage("no rcvr timeout after -t");
  1637.                     }
  1638.                     Rxtimeout = atoi(*++argv);
  1639.                     if(Rxtimeout<10 || Rxtimeout>1000)
  1640.                         usage("illegal timeout: must be 10 <= t <= 1000");
  1641.                     break;
  1642.                 case 'w':
  1643.                     if(--argc < 1)
  1644.                     {
  1645.                         usage("no Zrwindow after -w");
  1646.                     }
  1647.                     Zrwindow = atoi(*++argv);
  1648.                     break;
  1649.                 case 'C':
  1650.                     if(--argc < 1)
  1651.                         usage("no label after -C");
  1652.                     bottom_label = *++argv;
  1653.                     break;
  1654.                 case 'u':
  1655.                     MakeLCPathname=0;
  1656.                     break;
  1657.                 case 'y':
  1658.                     Rxclob=1;
  1659.                     break;
  1660.                 default:
  1661.                     sprintf(s128,"Unknown switch -%c",*cp);
  1662.                     usage(s128);
  1663.                 }
  1664.             }
  1665.         }
  1666.         else if( !npats && argc>0)
  1667.         {
  1668.             if(argv[0][0])
  1669.             {
  1670.                 npats=argc;
  1671.                 patts=argv;
  1672.             }
  1673.         }
  1674.     }
  1675.  
  1676.     if(!required_type || !iofd)
  1677.     {
  1678.         printf("can only be run by tip\n");
  1679.         exit(255);
  1680.     }
  1681.  
  1682.     if(log_packets)
  1683.     {
  1684.         char log_packets_name[64];
  1685.         FILE *ftmp;
  1686.         int iargv;
  1687.         sprintf(log_packets_name,"/tmp/rz%05d.plog",getpid());
  1688.         unlink(log_packets_name);
  1689.         ftmp = fopen(log_packets_name,"w");
  1690.         fclose(ftmp);
  1691.         log_packets = open(log_packets_name,O_WRONLY,0644);
  1692.         if(log_packets < 0)
  1693.             log_packets = 0;
  1694.         else
  1695.         {
  1696.             write(log_packets,"exec: ",6);
  1697.             for(iargv = 0; iargv < gargc; iargv++)
  1698.             {
  1699.                 write(log_packets,gargv[iargv],strlen(gargv[iargv]));
  1700.                 write(log_packets," ",1);
  1701.             }
  1702.             write(log_packets,"\n",1);
  1703.         }
  1704.     }
  1705.  
  1706.  
  1707.     if(Batch && npats)
  1708.         usage("Cannot specify batch receive and filename");
  1709.     if(npats > 1)
  1710.         usage("only one filename allowed");
  1711.     sprintf(s128,"%s",numeric_revision);
  1712.     report_init(s128);
  1713.     mode(1);
  1714.     signal(SIGINT,cancel_transaction);
  1715.     signal(SIGTERM,cancel_transaction);
  1716.     signal(SIGQUIT,cancel_transaction);
  1717.     if(wcreceive(npats,patts)==ERROR)
  1718.     {
  1719.         exitcode=0200;
  1720.         send_cancel();
  1721.     }
  1722.     mode(0);
  1723.     if(exitcode && !Zmodem)    /* bellow again with all thy might. */
  1724.         send_cancel();
  1725.     report_uninit(0);
  1726.     exit(exitcode);
  1727. }
  1728.  
  1729. /* vi: set tabstop=4 shiftwidth=4: */
  1730. /* end of tiprz.c */
  1731.